var WishListener = function () {
	this.listener = {};
};
WishListener.prototype = {
	//@method public void addListener (String name, Object listener)
	addListener : function (name, listener) {
		if (!this.listener[name]) this.listener[name] = [];
		this.listener[name].push(listener);
	},
	//@method public void removeListener (String name, Object listener)
	//@method public void removeListener (String name, int listener)
	removeListener : function (name, listener) {
		if (!this.listener[name]) return;
		if (!(this.listener[name] instanceof Array)) return;
		var index = listener;
		if (isNaN(listener)) {
			for (var i = 0; i < this.listener[name].length; i++) {
				if (this.listener[name][i] == listener) {
					index = i;
					break;
				}
			}
		}
		if (isNaN(index)) return;
		for (var i = index + 1; i < this.listener[name].length; i++) {
			this.listener[name][i - 1] = this.listener[name][i];
		}
		this.listener[name].pop();
	},
	//@method public Array getListeners (String name)
	getListeners : function (name) {
		if (!this.listener[name]) return [];
		if (!(this.listener[name] instanceof Array)) return [];
		return this.listener[name];
	},
	//@method public void trigger (String name, Array args)
	trigger : function (name, args) {
		var ls = this.getListeners(name);
		for (var i = 0; i < ls.length; i++) {
			ls[i][name].apply(this, args);
		}
	}
};

/**
 * @constructor
 * @param {String|JQuery el} domEl id of div or jquery el for div
 */
var WishStarGroup = function (domEl) {
	$.extend(this, new WishListener());
	this.listener = {
		beforeAddStar : [], //@interface function beforeAddStar (star, group)
		afterAddStar : [], //@interface function afterAddStar (star, group)
		beforeRemoveStar : [], //@interface function beforeRemoveStar (star, group)
		afterRemoveStar : [] //@interface function afterRemoveStar (star, group)
	};
	this.el = typeof domEl == 'string' ? $("#" + domEl) : domEl;
	this.el.addClass("wish-star-group");
	this.stars = [];
};

//@method public static void calcStarPosition (WishStarGroup group)
WishStarGroup.calcStarPosition = function (positions,group) {
	var stars = group.getStars();
	if(positions){
		var xys = positions.split(";");
		for (var i = 0; i < stars.length; i++) {
			if(xys.length > i){
				var xy = xys[i].split(',');
				stars[i].setPosition(xy[0], xy[1]);
				stars[i].setProperty('tips', xy[0] +',' + xy[1]);
			}
		}
	}else{
		var width = group.getWidth();
		var height = group.getHeight();
		for (var i = 0; i < stars.length; i++) {
			var left = parseInt(Math.random() * width);
			var right = parseInt(Math.random() * height);
			stars[i].setPosition(left, right);
		}
	}
};

WishStarGroup.prototype = {
	//@method publid void addStar (WishStar star)
	addStar : function (star) {
		this.trigger("beforeAddStar", [star, this]);
		this.stars.push(star);
		this.trigger("afterAddStar", [star, this]);
	},
	//@method public void removeStar (WishStar star)
	//@method public void removeStar (int star)
	removeStar : function (star) {
		var index = star;
		if (isNaN(star)) {
			for (var i = 0; i < this.stars.length; i++) {
				if (this.stars[i] == star) {
					index = i;
					break;
				}
			}
		}
		if (isNaN(index)) return;
		var s = this.stars[index];
		if (!s) return;
		this.trigger("beforeRemoveStar", [s, this]);
		for (var i = index + 1; i < this.stars.length; i++) {
			this.stars[i - 1] = this.stars[i];
		}
		this.stars.pop();
		this.trigger("afterRemoveStar", [s, this]);
		s.el.remove();
	},
	//@method public Array getStars ()
	getStars : function () {
		return this.stars || [];
	},
	//@method public int getWidth ()
	getWidth : function () {
		return this.el.outerWidth(true);
	},
	//@method public int getHeight ()
	getHeight : function () {
		return this.el.outerHeight(true);
	}
};

var WishStar = function (wishStarGroup, options) {
	$.extend(this, new WishListener());
	this.listener = {
		beforeGetProperty:[], //@interface function beforeGetProperty (name, star)
		afterGetPropery:[], //@interface function afterGetProperty (name, star)
		beforeSetProperty:[], //@interface function beforeSetProperty (name, newValue, star)
		afterSetProperty:[], //@interface function afterSetProperty (name, star)
		onClick : [], //@interface function onClick (star, evt)
		onMouseOver : [], //@interface function onMouseOver (star, evt)
		onMouseOut : [] //@interface function onMouseOut (star, evt)
	};
	this.wishStarGroup = wishStarGroup;
	this.wishStarGroup.addStar(this);
	$.extend(this, options || {});
	var showtips = true;
	var elContent = "<div class='wish-star'><div class='wish-star-img'></div>";
	if(showtips){
		elContent = elContent + "<div class='wish-star-tips'>" +this.getProperty("tips")+ "</div>";
	}
	elContent +="</div>";
	this.el = $(elContent);
	this.wishStarGroup.el.append(this.el);
	this.el.attr({title:this.getProperty("tips")});
	this._init();
};

WishStar.prototype = {
	//@method private void _init ()
	_init : function () {
		this.el.bind("click", this, function (e) {
			var self = e.data;
			self.trigger("onClick", [self, e]);
		});
		this.el.bind("mouseover", this, function (e) {
			var self = e.data;
			self.trigger("onMouseOver", [self, e]);
		});
		this.el.bind("mouseout", this, function (e) {
			var self = e.data;
			self.trigger("onMouseOut", [self, e]);
		});
	},
	//@method public Object getProperty (String name)
	getProperty : function (name) {
		this.trigger("beforeGetProperty", [name, this]);
		return this[name] || "";
		this.trigger("afterGetProperty", name, this);
	},
	//@method public void setProperty (String name, Object value)
	setProperty : function (name, value) {
		this.trigger("beforeSetProperty", [name, value, this]);
		this[name] = value;
		this.el.attr({title:value});
		this.trigger("afterSetProperty", [name, this]);
	},
	//@method public void setPosition (int left, int top)
	setPosition : function (left, top) {
		this.el.css('top',top+"px");
		this.el.css('left',left+"px");
		this.el.css('position','absolute');
	},
	//@method public int getWidth ()
	getWidth : function () {
		return this.el.outerWidth(true);
	},
	//@method public int getHeight ()
	getHeight : function () {
		return this.el.outerHeight(true);
	}
};